<script lang='ts' setup>
import { searchService } from '@/services/search.service';
import { onMounted, ref } from 'vue';
import MarkdownIt from '@/components/Markdown.vue';
import { appRef } from '@/models/app.ref';
import { SiderMenuEnum } from '@/models/@types';
import { DatabaseEnum, OnlineSearchInfo, OnlineSearchModelEnumOption } from '@/models/online-search';
import { bingService } from '@/services/bing.service';
import { publishService } from '@/services/publish.service';
import { arxivService } from '@/services/arxiv.service';
import { clipboardWriteText, getUuid, speechSynthesis } from '@/utils/common.methods';
import { Message } from '@arco-design/web-vue';
import router from '@/router';


const isSend = ref(false);
const textarea = ref('');
const result = ref('');

const menus = ref([]);
const currMenu = ref({} as OnlineSearchInfo);
onMounted(() => {
  init();
})

async function init(): Promise<void> {
  menus.value = await appRef.onlineSearch.menus();
  currMenu.value = appRef.onlineSearch?.currMenu;
  textarea.value = currMenu.value?.question;
  result.value = currMenu.value?.answer;
}

async function onAdd(e: { type: SiderMenuEnum, parent?: string }): Promise<void> {
  const { type, parent } = e
  await appRef.onlineSearch.add(type, parent);
  init();
}
async function onUpdate(enmus: OnlineSearchInfo[]): Promise<void> {
  await appRef.onlineSearch.updateEmuse(enmus)
  init();
}
async function onItem(uid: string): Promise<void> {
  console.log('onItem', uid);
  await appRef.onlineSearch.setCurrKey(uid);
  init();
}
async function onEdit(param: { uid: string, label: string }): Promise<void> {
  const { uid, label } = param;
  await appRef.onlineSearch.edit(uid, label);
}

const controllerKey = getUuid();

function onStopSend(): void {
  searchService.stopStream(controllerKey);
  isSend.value = false;
}

let isChunking = ref(false);
function onSend(): void {
  if (isChunking.value) return;
  result.value = '';
  isSend.value = true;
  const { database } = currMenu.value
  if (database === DatabaseEnum.Bing) {
    bingService.search(textarea.value).then(res => {
      res = 'bing search results: \n' + res + "\n The above information was obtained from the Internet and should be used to answer the following message in Chinese, \n each part of content must be followed by a referenced of the source url in markdown format:\n" + textarea.value;
      result.value = res;
      searchService.message(controllerKey, res, chunk, end)
    })
  } else if (database === DatabaseEnum.Arxiv) {
    arxivService.search(textarea.value).then(res => {
      res = 'arxiv search results:\n ' + res + "\n The above information was obtained from the Internet and should be used to answer the following message in Chinese, \n each part of content must be followed by a referenced of the source url in markdown format:\n" + textarea.value;
      result.value = res;
      searchService.message(controllerKey, res, chunk, end)
    })
  } else if (database === DatabaseEnum.Publish) {
    publishService.search(textarea.value).then(res => {
      res = 'publish scholar search results:\n ' + res + "\n The above information was obtained from the Internet and should be used to answer the following message in Chinese. The answer should not omit any potentially useful information. \n each part of content must be followed by a referenced of the source url in markdown format:\n" + textarea.value;
      result.value = res;
      searchService.message(controllerKey, res, chunk, end)
    })
  } else {
    searchService.search(controllerKey, textarea.value, chunk, end)
  }
}

function chunk(text: string): void {
  result.value += text;
  isChunking.value = true;
}

async function end(text: string): Promise<void> {
  isSend.value = false;
  await appRef.onlineSearch.update(currMenu.value.uid, textarea.value, text);
  result.value = text;
  isChunking.value = false;
}

function onCopy(richtext: string): void {
  clipboardWriteText(richtext).then(() => {
    Message.success('复制成功')
  })
}

function toMindMap(text: string): void {
  appRef.mindMap.add(SiderMenuEnum.Leaf);
  const curr = appRef.mindMap.currMenu;
  curr.originalWords = text;
  router.replace('/chat/mind-map');
}

</script>
<template>
  <div class="index">
    <a-layout style="height: 100%;">

      <a-layout>
        <div class="main flex-c" v-if="currMenu?.uid">
          <div class="bottom flex">
            <a-select v-model="currMenu.database" style="max-width:100px" placeholder="选择数据库">
              <a-option v-for="item in OnlineSearchModelEnumOption" :value="item.key" :label="item.name"></a-option>
            </a-select>
            <a-input class="input" v-model="textarea" placeholder="输入你想要搜索的关键词 ..." allow-clear :disabled="isSend"
              @keydown.enter="onSend" />
            <a-button class="send" type="primary" :disabled="!textarea || isChunking" @click.stop="onSend"
              :loading="isSend">
              <template #icon><icon-search style="width:40px;" /> </template>
            </a-button>
            <a-button class="stopSendbtn" status="warning" type="primary" v-if="isSend" @click="onStopSend">
              <template #icon> <icon-close /> </template>
              <span>停止响应</span>
            </a-button>
          </div>
          <a-spin class="flex-c spin" :loading="isSend" tip="搜索中">
            <div class="operates">
              <a-tooltip content="复制" mini>
                <icon-copy class="icon" @click="onCopy(result)" />
              </a-tooltip>
              <a-tooltip content="快速生成思维导图" mini>
                <icon-mind-mapping class="icon" @click="toMindMap(result)" />
              </a-tooltip>
              <a-tooltip content="语音播放" mini>
                <icon-customer-service class="icon" @click="speechSynthesis(result)" />
              </a-tooltip>
            </div>
            <MarkdownIt class="content" :source="result || '搜索总结的内容会显示在这里'"></MarkdownIt>
            <!-- <div class="content" v-html="result"> </div> -->
          </a-spin>
        </div>
        <Explanation v-else />
      </a-layout>
      <Sider :menus="menus" :default-uid="currMenu?.uid" @add="onAdd"
        @clear="async () => { await appRef.onlineSearch.clear(); init() }" @click-item="onItem"
        @edit="($event) => { onEdit($event); init() }"
        @remove="async ($event) => { await appRef.onlineSearch.remove($event); init() }"
        @update="($event) => onUpdate($event)" />
    </a-layout>
  </div>
</template>
<style lang='scss' scoped>
.index {
  height: 100%;

  .main {
    width: 95%;
    height: 100%;
    justify-content: center;
    max-width: 1270px;
    margin: 0 auto;
    padding: 20px 0;

    .spin {
      width: 100%;
      flex: 1;
      overflow: hidden;
      background: var(--color-neutral-2);
      margin-top: 20px;

      .operates {
        width: 100%;
        padding: 20px 20px 0;
        margin-bottom: -20px;

        .icon {
          cursor: pointer;
          margin: 0 5px;
          font-size: 20px;
        }
      }
    }

    .content {
      width: 100%;
      margin: 20px;
      margin-bottom: 0;
      background: var(--color-neutral-2);
      line-height: 20px;
      overflow: auto;
      flex: 1;
      word-break: break-all;
    }

    .bottom {
      background: var(--color-neutral-2);
      width: 100%;
      padding: 10px 20px;
      position: relative;


      .input {
        height: 100%;
        margin-right: 10px;
        background: none;

        input {
          &:focus {
            border: none !important;
          }
        }

      }

      .stopSendbtn {
        position: absolute;
        left: 50%;
        bottom: -30px;
        z-index: 15;
        transform: translateX(-50%);
      }


    }
  }
}
</style>
